package com.ruicar.afs.cloud.filecenter.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.filecenter.config.FileProperties;
import com.ruicar.afs.cloud.filecenter.entity.AfsFileInfo;
import com.ruicar.afs.cloud.filecenter.entity.AfsFileStore;
import com.ruicar.afs.cloud.filecenter.enums.ProcessStatus;
import com.ruicar.afs.cloud.filecenter.service.IFileChunkService;
import com.ruicar.afs.cloud.filecenter.service.IFileInfoService;
import com.ruicar.afs.cloud.filecenter.service.IFileProcess;
import com.ruicar.afs.cloud.filecenter.service.IFileStoreService;
import com.ruicar.afs.cloud.filecenter.vo.ChunkInfo;
import com.ruicar.afs.cloud.filecenter.vo.FileStoreVo;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;

/**
 * FileStoreController
 * <p>Description: </p>
 *
 * @author Fzero
 * @version 1.0
 * @date create on 20191224 04:29:25
 * @since 1.0
 */
@Slf4j
@Api(tags = "文件中心")
@RestController
@RequestMapping("/filestore")
@AllArgsConstructor
public class FileStoreController {

    /**
     * Ifile store service
     * <p>Description: </p>
     */
    private final IFileStoreService ifileStoreService;
    /**
     * File chunk service
     * <p>Description: </p>
     */
    private final IFileChunkService iFileChunkService;
    /**
     * File process
     * <p>Description: </p>
     */
    private final IFileProcess iFileProcess;

    /**
     * File info service
     * <p>Description: </p>
     */
    private final IFileInfoService fileInfoService;

    private final FileProperties fileProperties;

    /**
     * Upload response
     * <p>Description: </p>
     *
     * @param file             file
     * @param md5              md 5
     * @param chunkNumber      chunk number
     * @param currentChunkSize current chunk size
     * @param totalChunks      total chunks
     * @param totalSize        total size
     * @param guid         filename
     * @return the response
     */
    @PostMapping("/store")
    public IResponse<FileStoreVo> upload(@RequestParam("file") MultipartFile file,
                                         @RequestParam("md5") String md5,
                                         @RequestParam("chunkNumber") int chunkNumber,
                                         @RequestParam("currentChunkSize") int currentChunkSize,
                                         @RequestParam("totalChunks") int totalChunks,
                                         @RequestParam("signature") String signature,
                                         @RequestParam("totalSize") long totalSize,
                                         @RequestParam("guid") String guid
    ) {
        if(!iFileProcess.checkFileSize(file.getOriginalFilename(),totalSize)){
            return IResponse.fail("文件过大").setCode(ProcessStatus.OVERSIZE.getCode());
        }
        if(!iFileProcess.checkFileSignature(file.getOriginalFilename(),md5,signature)){
            return IResponse.fail("文件不合法").setCode(ProcessStatus.ILLEGAL.getCode());
        }
        return IResponse.success(ifileStoreService.storeFile(file, md5, chunkNumber, currentChunkSize, totalChunks, totalSize, guid));
    }

    /**
     * Check chunk info response
     * <p>Description: </p>
     *
     * @param md5         md 5
     * @param chunkNumber chunk number
     * @param totalChunks total chunks
     * @return the response
     */
    @GetMapping("/store")
    public IResponse<ChunkInfo> checkChunkInfo(@RequestParam("filename") String filename,
                                               @RequestParam("md5") String md5,
                                               @RequestParam("chunkNumber") int chunkNumber,
                                               @RequestParam("totalChunks") int totalChunks,
                                               @RequestParam("signature") String signature,
                                               @RequestParam("totalSize") long totalSize,
                                               @RequestParam("guid") String guid) {
        if(!iFileProcess.checkFileSize(filename,totalSize)){
            return IResponse.fail("文件过大").setCode(ProcessStatus.OVERSIZE.getCode());
        }
        if(!iFileProcess.checkFileSignature(filename,md5,signature)){
            return IResponse.fail("文件不合法").setCode(ProcessStatus.ILLEGAL.getCode());
        }
        return IResponse.success(iFileChunkService.checkChunkInfo(filename,md5, chunkNumber, totalChunks,guid));
    }

    /**
     * Merge response
     * <p>Description: </p>
     *
     * @param md5 md 5
     * @param guid  id
     * @return the response
     */
    @PostMapping("/merge")
    public IResponse<ChunkInfo> merge(@RequestParam("filename") String filename,
                                      @RequestParam("md5") String md5,
                                      @RequestParam("signature") String signature,
                                      @RequestParam("guid") String  guid) {
        if(!iFileProcess.checkFileSignature(filename,md5,signature)){
            return IResponse.fail("文件不合法").setCode(ProcessStatus.ILLEGAL.getCode());
        }
        return IResponse.success(iFileProcess.mergeFile(md5, guid));
    }

    /**
     * Delete file response
     * <p>Description: </p>
     *
     * @param accessKey access key
     * @return the response
     */
    @PostMapping("/delete")
    public IResponse<ChunkInfo> deleteFile(@RequestParam("accessKey") String accessKey) {
        return IResponse.success(iFileProcess.deleteFile(accessKey));
    }

    /**
     * Down file by access key *
     *
     * @param response  response
     * @param type      type   0-原始文件,thumbnail-缩略图,jpg-转换后的jpg文件,pdf-转换成pdf 的文件
     * @param accessKey access key,单个文件下载将来由nginx 代理目录进行？
     * 单个文件下载，type--
     */
    @GetMapping("/file/{type}/{accessKey}")
    public void downFileByAccessKey(HttpServletResponse response,@PathVariable ("type") String type, @PathVariable ("accessKey") String accessKey){
        //todo 扩展配置中获取
        BufferedInputStream bufferedInputStream = null;
        try {
            AfsFileInfo afsFileInfo = fileInfoService.getOne(Wrappers.<AfsFileInfo>lambdaQuery().eq(AfsFileInfo::getAccessKey,accessKey),false);
            String filePath = null;
            if(afsFileInfo !=null){
                AfsFileStore afsFileStore =  ifileStoreService.getOne(Wrappers.<AfsFileStore>lambdaQuery().eq(AfsFileStore::getMd5Value, afsFileInfo.getFileMd5()),false);
                if(afsFileStore !=null){
                    filePath = fileProperties.getTempDir()+ File.separator+ afsFileStore.getFilePath();
                    if (FileUtil.exist(filePath)) {
                        bufferedInputStream = FileUtil.getInputStream(filePath);
                        response.setContentType(afsFileInfo.getFileMime());
                        response.setHeader("Content-Disposition", "attachment; filename="+HttpUtil.encodeUtf8(afsFileInfo.getFileName()));
                        IoUtil.copy(bufferedInputStream,response.getOutputStream(),1024);
                        response.getOutputStream().flush();
                        return;
                    }
                }
            }
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }catch (IOException e){
            log.error("读取文件失败",e);
        }finally {
            IoUtil.close(bufferedInputStream);
        }
    }
}
